home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
textool
/
pkstuff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
14KB
|
619 lines
/*
* This is the font part of textool, dealing with PK format files.
* The low level routines to deal with the PK format
* were transliterated from pktopx
* See the pktopx documentation for details.
* For V2.3, 29 Mar 88
- * Fixed stupid errors in skip_specials() that caused specials to be
missed
*/
#include "defs.h"
#include <stdio.h>
#include <sys/file.h> /* for access() stuff */
#include <pixrect/pixrect_hs.h> /* for LoadAChar() */
char *index();
int strlen();
char *strcpy();
char *sprintf();
/* procedures in sunstuff */
extern void Fatal();
extern void Warning();
/* procedures in dvistuff */
extern float ActualFactor();
extern FILE *OpenFontFile();
/* procedures here */
void ReadCharDefs();
void LoadAChar();
/* a few global variables and data structures */
#include "globals.h"
#define PK_XXX1 240
#define PK_XXX2 241
#define PK_XXX3 242
#define PK_XXX4 243
#define PK_YYY 244
#define PK_POST 245
#define PK_NOP 246
#define PK_PRE 247
#define PK_ID 89
#define ROWSIZE 64 /* maximum width of raster in 16 bit words */
static FILE *pkfp;
static long pk_loc; /* points to next byte to be read in file */
static long pk_char_start;
static int repeat_count;
static int dyn_f;
static int word_width;
static int char_height;
static int char_width;
static Boolean got_pk_post;
static Boolean turn_on;
static int bit_weight;
static int flag_byte;
static int packet_length;
static int char_code;
static int tfm_width;
static int hor_esc;
static int vert_esc;
static int h_off;
static int v_off;
static int nybindex;
static short row[ROWSIZE];
static short *rowptr;
static short *imageptr;
static int power[16] =
{1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000};
static int gpower[17] =
{0, 1, 3, 7, 15, 0x1f, 0x3f, 0x7f,
0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
#define get_pk_byte() (pk_loc++, getc(pkfp))
int
get_pk_word()
{
int myword;
myword = get_pk_byte() << 8;
return (myword + get_pk_byte());
}
int
get_pk_double()
{
register int mydouble;
mydouble = get_pk_byte() << 8;
mydouble += get_pk_byte();
mydouble = (mydouble << 8) + get_pk_byte();
return ((mydouble << 8) + get_pk_byte());
}
/*
* This returns the next nybble from the pk file
* The variable nybindex controls which nybble is
* returned. This is initialised to 0 in normal_raster()
* as a previous normal_raster() may have read an odd
* number of nybbles.
*/
int
get_pk_nybble()
{
static int mynybble;
if (nybindex) {
nybindex = 0;
return (mynybble & 0xf);
}
else {
mynybble = get_pk_byte();
nybindex = 1;
return (mynybble >> 4);
}
}
/*
* This returns a non-zero value if the next pk file
* bit is a one. It is only used in an if (..) so
* the actual value is not important.
* The variable bit_weight is used to count the bits
* between calls to get_pk_byte(). It is initialised
* to 0 in bitmap_raster() so a byte is fetched the
* first time.
* The function is given for illustration. The macro
* following is used for speed.
*/
/*
*int
*get_pk_bit()
*{
* static int byte_for_bits;
*
* if (bit_weight <= 1) {
* bit_weight = 256;
* byte_for_bits = get_pk_byte();
* }
* bit_weight = bit_weight >> 1;
* return (byte_for_bits & bit_weight);
*}
*/
static int byte_for_bits;
#define get_pk_bit() (((bit_weight<=1) ?\
(bit_weight = 128, byte_for_bits=get_pk_byte()) : (bit_weight>>=1)),\
byte_for_bits&bit_weight)
void
send_row()
{
register short *dp;
register int i;
register int repcount;
dp = imageptr;
repcount = repeat_count + 1;
while (repcount--) {
rowptr = row;
i = word_width;
while(i--)
*dp++ = *rowptr++;
}
imageptr=dp; /* save for next call */
}
void
skip_specials()
{
register int i;
do {
i = 0;
flag_byte = get_pk_byte();
if (flag_byte >= PK_XXX1)
switch (flag_byte) {
case PK_XXX4:
i = get_pk_byte();
case PK_XXX3:
i = (i<<8) + get_pk_byte();
case PK_XXX2:
i = (i<<8) + get_pk_byte();
case PK_XXX1:
i = (i<<8) + get_pk_byte();
while (i--)
(void)get_pk_byte();
break;
case PK_YYY:
(void)get_pk_double();
break;
case PK_POST:
#ifdef DEBUG
if (ExtraDebug)
fprintf(stderr, "Got pk_post in skip_specials()\n");
#endif
got_pk_post = TRUE;
return;
case PK_NOP:
break;
default:
Fatal("Bad pk command byte (%d) in skip_specials()",
flag_byte);
return;
}
} while (flag_byte >= PK_XXX1);
}
/*
* This routine returns the next run count from the pk
* character description. It will set the global repeat_count
* to any repeat count value encountered.
*/
int
pk_packed_num()
{
register int i, j;
i = get_pk_nybble();
if (i == 0) {
do {
j = get_pk_nybble();
i++;
} while (j == 0);
while (i--)
j = (j<<4) + get_pk_nybble();
return (j - 15 + ((13 - dyn_f)<<4) + dyn_f);
}
else if (i <= dyn_f)
return (i);
else if (i < 14)
return (((i - dyn_f - 1)<<4) + get_pk_nybble() + dyn_f + 1);
else {
if (i == 14)
repeat_count = pk_packed_num();
else /* i must be 15 */
repeat_count = 1;
return (pk_packed_num());
}
}
/*
* This deals with run count encoded rasters.
* It uses pk_packed_num() which in turn uses get_pk_nybble().
*/
void
normal_raster(dp)
short *dp;
{
register int word = 0;
register int count;
register int h_bit = char_width;
register int word_weight = 16;
register int rows_left = char_height;
repeat_count = 0;
nybindex = 0;
imageptr = dp;
rowptr = row;
while (rows_left > 0) {
count = pk_packed_num();
while (count > 0) {
if ((count < word_weight) && (count < h_bit)) {
if (turn_on)
word += gpower[word_weight] - gpower[word_weight - count];
h_bit -= count;
word_weight -= count;
count = 0;
}
else if ((count >= h_bit) && (h_bit <= word_weight)) {
if (turn_on)
word += gpower[word_weight] - gpower[word_weight - h_bit];
*rowptr++ = word;
send_row();
rowptr = row;
rows_left -= repeat_count + 1;
repeat_count = 0;
word = 0;
word_weight = 16;
count -= h_bit;
h_bit = char_width;
}
else {
if (turn_on)
word += gpower[word_weight];
*rowptr++ = word;
word = 0;
count -= word_weight;
h_bit -= word_weight;
word_weight = 16;
}
}
turn_on ^= 1;
}
if ((rows_left != 0) || (h_bit != char_width)) {
Fatal("Bad pk file - more bits than required\n");
return;
}
}
/*
* This deals with bit mapped raster (dyn_f = 14).
* It uses get_pk_bit().
*/
void
bitmap_raster(dp)
short *dp;
{
register int i;
register int j;
register int word;
register int word_weight;
bit_weight = 0;
for (i = 0; i < char_height; i++) {
word = 0;
word_weight = 15;
for (j = 0; j < char_width; j++) {
if (get_pk_bit())
word += power[word_weight];
if (word_weight-- == 0) {
*dp++ = word;
word = 0;
word_weight = 15;
}
}
if (word_weight < 15)
*dp++ = word;
}
}
/*
* This reads the pk file preamble and rejects the file
* if it does not start correctly.
*/
void
get_pk_preamble()
{
register int comment_length;
got_pk_post = FALSE;
fseek(pkfp, 0L, 0);
pk_loc = 0;
if (get_pk_byte() != PK_PRE) {
Fatal("Bad pk file - doesn't start with pk_pre\n");
return;
}
if (get_pk_byte() != PK_ID) {
Fatal("Bad pk file - wrong pk_id byte\n");
return;
}
comment_length = get_pk_byte();
while (comment_length--)
get_pk_byte();
(void)get_pk_double();
(void)get_pk_double();
(void)get_pk_double();
(void)get_pk_double();
}
/*
* This reads the preamble for one character up to the tfm width.
* The tfm width is read as when it is stored in the char_entry
* struct it needs to be multiplied by the font "s" parameter.
* ReadCharDefs() is passed a pointer to the font_entry struct
* so it can do this whereas LoadAChar() can't.
* The rest of the char will either be skipped or read with
* get_pk_char_dimen().
* flag_byte will have been set by a previous skip_specials().
*/
void
get_pk_char_code()
{
dyn_f = flag_byte >> 4;
turn_on = (flag_byte & 0x8) >> 3;
flag_byte &= 0x7;
pk_char_start = pk_loc - 1; /* - 1 as flag byte has been read */
if (flag_byte < 4) { /* short preamble */
packet_length = (flag_byte << 8) + get_pk_byte();
char_code = get_pk_byte();
tfm_width = get_pk_byte() << 16;
tfm_width += get_pk_word();
packet_length -= 3; /* correct for reading tfm_width */
}
else if (flag_byte < 7) { /* extended short preamble */
packet_length = ((flag_byte - 4) << 16) + get_pk_word();
char_code = get_pk_byte();
tfm_width = get_pk_byte() << 16;
tfm_width += get_pk_word();
packet_length -= 3;
}
else { /* long preamble */
packet_length = get_pk_double();
char_code = get_pk_double();
tfm_width = get_pk_double();
packet_length -= 4;
}
}
/*
* This reads the char preamble starting after the tfm width,
* carrying on where get_pk_char_code() left off.
*/
void
get_pk_char_dimen()
{
if (flag_byte < 4) { /* short preamble */
hor_esc = get_pk_byte();
char_width = get_pk_byte();
word_width = (char_width + 15)>>4;
char_height = get_pk_byte();
h_off = (char)get_pk_byte();
v_off = (char)get_pk_byte();
}
else if (flag_byte < 7) { /* extended short preamble */
hor_esc = get_pk_word();
char_width = get_pk_word();
word_width = (char_width + 15)>>4;
char_height = get_pk_word();
h_off = (short)get_pk_word();
v_off = (short)get_pk_word();
}
else { /* long preamble */
hor_esc = get_pk_double();
vert_esc = get_pk_double();
char_width = get_pk_double();
word_width = (char_width + 15)>>4;
char_height = get_pk_double();
h_off = get_pk_double();
v_off = get_pk_double();
}
}
/*
* This reads the preamble for one character.
*/
void
get_pk_char_preamble()
{
flag_byte = get_pk_byte();
get_pk_char_code();
get_pk_char_dimen();
}
/*
* Now here are the routines called by the rest of textool
*/
/*-->FindFontFile*/
void
FindFontFile(tfontptr, mag)
struct font_entry *tfontptr;
unsigned int mag;
{
char *direct, *tcp, *tcp1;
int found;
char curarea[STRSIZE];
tfontptr->font_mag = (int)(
ActualFactor((int)(((float)tfontptr->s/(float)tfontptr->d)*1000.0+0.5))
#ifdef USEGLOBALMAG
* ActualFactor(mag)
#endif
* (float)RESOLUTION + 0.5);
#ifdef DEBUG
if (ExtraDebug) {
fprintf(stderr, "FindFontFile():\n");
fprintf(stderr, " mag = %d\n", mag);
fprintf(stderr, " s = %d\n", tfontptr->s);
fprintf(stderr, " d = %d\n", tfontptr->d);
fprintf(stderr, " font_mag = %d\n", tfontptr->font_mag);
}
#endif
if (tfontptr->a != 0) {
sprintf(tfontptr->name, "%s.%dpk", tfontptr->n, tfontptr->font_mag);
} else {
direct = PKpath;
found = FALSE;
do {
tcp = index(direct, ':');
if (tcp == NULL) tcp = strlen(direct) + direct;
strncpy(curarea, direct, tcp-direct);
tcp1 = curarea + (tcp - direct);
*tcp1++ = '/';
*tcp1++ = '\0';
sprintf(tfontptr->name, "%s%s.%dpk",
curarea, tfontptr->n, tfontptr->font_mag);
found = (access(tfontptr->name, R_OK) == 0);
if (*tcp) direct = tcp + 1; else direct = tcp;
} while ( !found && *direct != '\0');
}
#ifdef DEBUG
if (ExtraDebug)
fprintf(stderr, "FindFontFile() returns with name %s\n",
tfontptr->name);
#endif
}
/*-->LoadAChar*/
void
LoadAChar(ptr)
register struct char_entry *ptr;
{
register Pixrect *pr;
register short *dp;
pkfp = OpenFontFile();
if (ptr->where.address.fileOffset == 0) {
ptr->where.address.pixrectptr = NULL;
return;
}
fseek(pkfp, ptr->where.address.fileOffset, 0);
get_pk_char_preamble();
ptr->width = char_width;
ptr->height = char_height;
ptr->xOffset= h_off;
ptr->yOffset = v_off;
if ((pr = mem_create(ptr->width, ptr->height, 1)) == NULL) {
Fatal("Couldn't allocate pixrect");
return;
}
dp = ((struct mpr_data *)pr->pr_data)->md_image;
if (dyn_f == 14)
bitmap_raster(dp);
else
normal_raster(dp);
ptr->where.address.pixrectptr = pr;
ptr->where.isloaded = TRUE;
}
/*-->ReadCharDefs*/
void
ReadCharDefs(tfontptr, fp)
struct font_entry *tfontptr;
FILE *fp;
{
register struct char_entry *tcharptr; /* temporary char_entry pointer */
register Pixrect *pr;
register int junk_count;
short *dp;
#ifdef DEBUG
if (ExtraDebug)
fprintf(stderr, "ReadCharDefs() for font %s\n", tfontptr->name);
#endif
pkfp = fp;
get_pk_preamble();
skip_specials();
while (!got_pk_post) {
get_pk_char_code();
tcharptr = &(tfontptr->ch[char_code]);
tcharptr->tfmw = tfm_width * (float)tfontptr->s / (float)(1<<20);
if (BigPreLoad) {
/*
* Load the rest of the character info.
*/
get_pk_char_dimen();
tcharptr->width = char_width;
tcharptr->height = char_height;
tcharptr->xOffset= h_off;
tcharptr->yOffset = v_off;
if ((pr = mem_create(char_width, char_height, 1)) == NULL) {
Fatal("Couldn't allocate pixrect");
return;
}
dp = ((struct mpr_data *)pr->pr_data)->md_image;
if (dyn_f == 14)
bitmap_raster(dp);
else
normal_raster(dp);
tcharptr->where.address.pixrectptr = pr;
tcharptr->where.isloaded = TRUE;
}
else {
tcharptr->where.isloaded = FALSE;
tcharptr->where.address.fileOffset = pk_char_start;
/*
* Otherwise skip the rest of the char.
* The bytes are read rather than using fseek as the pk files
* are small and the whole thing is likely to fit in one stdio
* buffer so this will not involve any function calls.
*/
junk_count = packet_length;
while (junk_count--)
getc(pkfp);
pk_loc += packet_length;
}
skip_specials();
}
}